package com.be.beadmin.project.Util;

import com.alibaba.excel.util.StringUtils;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.project.config.MinioConfig;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;

import io.minio.errors.*;
import io.minio.messages.CopyObjectResult;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.rmi.ServerException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;


/**
 * @Author: Mengyang Zhu
 * @Date: 2023/2/15 15:56
 * @Description: MinioUtil
 */
@Component
public class MinioUtil {

    public String getPreviewFileUrl(String bucketName, String fileName) throws Exception{
        MinioClient minioClient = MinioConfig.getMinioClient();
        return minioClient.presignedGetObject(bucketName, fileName);
    }


    public String uploadFile2(MultipartFile file,String fileName,String bucketName)throws Exception {

            MinioClient minioClient = MinioConfig.getMinioClient();
            InputStream inputStream = file.getInputStream();

            PutObjectOptions putObjectOptions = new PutObjectOptions(file.getInputStream().available(), -1);
            putObjectOptions.setContentType(file.getContentType());

            minioClient.putObject(bucketName, fileName, inputStream, putObjectOptions);
            inputStream.close();
            return getPreviewFileUrl(bucketName, fileName);
    }

    //上传文件
    public void uploadFile(MultipartFile file,String fileName,String bucketName) throws Exception {
        //String fileName = file.getName();
        System.out.println(fileName);
        MinioClient minioClient = MinioConfig.getMinioClient();
        InputStream is = file.getInputStream();
        minioClient.putObject(bucketName, fileName, is, new PutObjectOptions(is.available(), -1));
        is.close();
    }

    //预览文件
    public String getReadFile(String bucketName,String fileName) throws Exception {
        MinioClient minioClient = MinioConfig.getMinioClient();
        String url = minioClient.presignedGetObject(bucketName,fileName);
        return url;
    }
    //可预览文件 TANG
    public static String uploadFile3(MultipartFile multipartFile,String bucketName, String fileName)throws Exception {
        MinioClient minioClient = MinioConfig.getMinioClient();
        PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getInputStream().available(), -1);
        putObjectOptions.setContentType(multipartFile.getContentType());
        InputStream inputStream = multipartFile.getInputStream();
        minioClient.putObject(bucketName, fileName, inputStream, putObjectOptions);
        return minioClient.presignedGetObject(bucketName, fileName);
    }

    public MultipartFile getMultipartFile(String bucketName, String objectName) throws IOException, MinioException, NoSuchAlgorithmException, InvalidKeyException {
        MinioClient minioClient = MinioConfig.getMinioClient();
        try (InputStream objectStream = minioClient.getObject(bucketName, objectName)) {
            // 从MinIO中获取对象流，然后创建一个MultipartFile对象
            String name = objectName.substring(0,objectName.indexOf("-"))+objectName.substring(objectName.lastIndexOf("."));
            return new MinioMultipartFile(name, objectStream);
        }
    }

    public MultipartFile getMultipartFile(String bucketName, String objectName,String fileName) throws IOException, MinioException, NoSuchAlgorithmException, InvalidKeyException {
        MinioClient minioClient = MinioConfig.getMinioClient();
        try (InputStream objectStream = minioClient.getObject(bucketName, objectName)) {
            // 从MinIO中获取对象流，然后创建一个MultipartFile对象
//            String name = objectName.substring(0,objectName.indexOf("-"))+objectName.substring(objectName.lastIndexOf("."));
            return new MinioMultipartFile(fileName, objectStream);
        }
    }

    /**
     * 拷贝文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param srcBucketName 目标bucket名称
     * @param srcObjectName 目标文件名称
     */
    public  void copyObject(String bucketName, String objectName,
                                                 String srcBucketName, String srcObjectName)
            throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException, InvalidPortException, InvalidEndpointException {

        MinioClient minioClient = MinioConfig.getMinioClient();

        minioClient.copyObject(
                bucketName,
                objectName,
                null,
                null,
                srcBucketName,
                srcObjectName,
                null,
                null);


    }

    private static class MinioMultipartFile implements MultipartFile {
        private final String name;
        private final InputStream inputStream;

        public MinioMultipartFile(String name, InputStream inputStream) {
            this.name = name;
            this.inputStream = inputStream;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getOriginalFilename() {
            return name;
        }

        @Override
        public String getContentType() {
            return "application/octet-stream"; // 根据实际情况设置内容类型
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        @Override
        public long getSize() {
            return -1; // 未知大小
        }

        @Override
        public byte[] getBytes() throws IOException {
            // 在实际使用时可能需要将输入流的内容读取到字节数组中
            throw new UnsupportedOperationException("getBytes() is not supported");
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return inputStream;
        }

        @Override
        public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
            // 在实际使用时可能需要将输入流的内容传输到指定的文件
            throw new UnsupportedOperationException("transferTo() is not supported");
        }
    }


    //下载文件
    public InputStream   downloadFile(String bucketName, String fileName, HttpServletResponse response)  {
        try {
            MinioClient minioClient = MinioConfig.getMinioClient();
            InputStream file = minioClient.getObject(bucketName,fileName);

            //response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName.substring(fileName.indexOf("-")+1),"UTF-8").replace("+", " "));
            response.setCharacterEncoding("UTF-8");
            ServletOutputStream servletOutputStream = response.getOutputStream();
            int len;
            byte[] buffer = new byte[1024];
            while ((len = file.read(buffer)) > 0) {
                servletOutputStream.write(buffer, 0, len);
            }

            servletOutputStream.flush();
            file.close();
            servletOutputStream.close();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    public void   downloadFile2(String bucketName, String fileName, HttpServletResponse response)  throws Exception {
        InputStream inputStream   = null;
        OutputStream outputStream = null;
        MinioClient minioClient = MinioConfig.getMinioClient();
        try {
            if (StringUtils.isBlank(fileName)) {
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                String data = "文件下载失败";
                OutputStream ps = response.getOutputStream();
                ps.write(data.getBytes("UTF-8"));
                return;
            }

            outputStream = response.getOutputStream();
            // 获取文件对象
            inputStream =minioClient.getObject(bucketName,fileName);
            byte buf[] = new byte[1024];
            int length = 0;
            response.reset();
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName.substring(fileName.lastIndexOf("/") + 1), "UTF-8"));
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("UTF-8");
            // 输出文件
            while ((length = inputStream.read(buf)) > 0) {
                outputStream.write(buf, 0, length);
            }
            inputStream.close();

        } catch (Throwable ex) {
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            String data = "文件下载失败";
            try {
                OutputStream ps = response.getOutputStream();
                ps.write(data.getBytes("UTF-8"));
            }catch (IOException e){
                e.printStackTrace();
            }
        } finally {
            try {
                outputStream.close();
                if (inputStream != null) {
                    inputStream.close();
                }}catch (IOException e){
                e.printStackTrace();
            }
        }

    }

    //判断bucket是否存在
    public boolean bucketExists(String bucketName) throws InvalidPortException, InvalidEndpointException {
        MinioClient minioClient = MinioConfig.getMinioClient();
        boolean flag = false;
        try {
            flag = minioClient.bucketExists(bucketName);
            if (flag) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }


    //创建bucket
    public  void createBucketName(String bucketName) {

        try {
            if (StringUtils.isBlank(bucketName)) {
                return;
            }
            MinioClient minioClient = MinioConfig.getMinioClient();
            boolean isExist = minioClient.bucketExists(bucketName);
            if (isExist) {

                System.out.println("Bucket already exists.");
                throw new Exception("Bucket already exists.");
            } else {
                minioClient.makeBucket(bucketName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean removeObject(String bucketName,String objectName) throws InvalidPortException, InvalidEndpointException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        MinioClient minioClient = MinioConfig.getMinioClient();
        try {
            boolean exists = bucketExists(bucketName);
            if (exists) {
                minioClient.removeObject(bucketName, objectName);
                return true;
            }
        } catch (Exception e){
            throw new BeadminException("removeObject:",e);
        }
        return false;
    }

}
